package pizza.util;
/** an abstract class for implementations of the Enumeration interface
*/
public abstract class Enumerator implements Enumeration {
/** the Enumeration methods
*/
public abstract boolean hasMoreElements();
public abstract A nextElement();
/** concat another enumerator, to be called when this one is done
*/
public Enumerator concat(Enumerator rest) {
return new CompositeEnumerator(this, rest);
}
/** return enumerator that yields `f' applied to each element
* of this enumerator
*/
public Enumerator map((A)->B f) {
return new MapEnumerator(f, this);
}
/** return elements of this enumerator as long as predicate `p' is true
*/
public Enumerator takeWhile((A)->boolean p) {
return new TakeWhileEnumerator(p, this);
}
/** return enumerator that starts with the first element of this
* enumerator for which `p' holds, and then continues with all
* subsequent elements of this enumerator
*/
public Enumerator dropWhile((A)->boolean p) {
return new DropWhileEnumerator(p, this);
}
/** return enumerator that yields all element of this enumerator that
* satisfy predicate `p'.
*/
public Enumerator filter((A)->boolean p) {
return new FilterEnumerator(p, this);
}
/** apply function `f' to all elements of this enumerator
*/
public void forall((A)->B f) {
while (hasMoreElements()) f(nextElement());
}
/** reduce all elements of this enumerator with binary operation `f',
* starting with `z'. Operations are grouped to the left.
*/
public B reduceLeft(B z, (B,A)->B f) {
while (hasMoreElements()) z = f(z, nextElement());
return z;
}
/** reduce all elements of this enumerator with binary operation `f',
* starting with `z'. Operations are grouped to the right.
*/
public B reduceRight((A,B)->B f, B z) {
if (hasMoreElements()) return f(nextElement(), reduceRight(f, z));
else return z;
}
}
/** A class for the empty enumerator, which yields no elements
*/
public class SingletonEnumerator extends Enumerator {
A value;
boolean unseen = true;
public SingletonEnumerator(A value) {
this.value = value;
}
public boolean hasMoreElements() {
return unseen;
}
public A nextElement() {
if (unseen) {
unseen = false;
return value;
} else {
throw new NoSuchElementException();
}
}
}